import { cloneDeep, round } from 'lodash'
import { indexToPlot } from '@/utils/utils'
export default class SpectrumMarker {
  constructor(chart, index = 1, dragMarker) {
    this.chart = chart // 图表实例
    this.index = index
    this.allNum = 6
    this.marker = null // 标记点renderer定义 svg > path
    this.plotX = 0 // 坐标轴x位置
    this.point = null // 该频标在实时线上的基准点
    if (!chart.specturmMarkers) {
      chart.specturmMarkers = [this]
    } else {
      chart.specturmMarkers.push(this)
    }
    this.visible = true
    this.dragMarker = dragMarker
    this.plotX = (this.chart.plotSizeX * this.index) / this.allNum
    this.markerPoint()
  }
  markerPoint() {
    const point = this.findClosestPoint(this.chart.series[0])
    this.setPointInfo(point)
    this.drawCustomShape()
  }
  drawCustomShape() {
    this.destroy()
    const renderer = this.chart.renderer
    const x = this.point.plotX + this.chart.plotLeft
    // const y = this.point.plotY + this.chart.plotTop
    const y = this.chart.plotSizeY + this.chart.plotTop
    var path = [] // 添加路径
    path.push('M', x - 12, y) // 移动到起始点
    path.push('L', x + 12, y) // 画一条线
    path.push('L', x, y - 24) // 画一条线
    path.push('Z') // 关闭路径  // 将路径添加到图表中
    path.push('M', x, y - 24)
    path.push('L', x, this.chart.plotTop)
    const strokeColor = this.isActive ? '#557395' : '#aeadad'
    const fillColor = this.isActive ? '#0d2b56' : '#aeadad'
    this.marker = renderer
      .path(path)
      .attr({ stroke: strokeColor, 'stroke-width': 1, fill: fillColor, zIndex: 4 })
    this.text = renderer.text(this.index, x - 5, y - 2).attr({
      zIndex: 5,
      fill: 'rgba(1, 23, 13, 1)',
      style: `fill: ${this.isActive ? '#f3f3f3' : '#333'};`
    })
    this.x = x
    this.marker.add()
    this.text.add()
    if (this.isActive) {
      this.addDialog(x, y)
    }
    this.registeDragEvents()
  }
  setPointInfo(point) {
    this.point = point
    this.coorX = point.x
    this.plotX = point.plotX
  }
  addDialog(x, y) {
    const renderer = this.chart.renderer
    const path = [
      'M',
      x + 36.5,
      y - 31.5,
      'L',
      x + 43.5,
      y - 37.5,
      'M',
      x + 43.5,
      y - 31.5,
      'L',
      x + 36.5,
      y - 37.5
    ]
    const ctx = this
    this.dialog = {
      rect: renderer
        .rect(x - 50, y - 44, 100, 20, 5)
        .attr({ stroke: '#557395', fill: '#0d2b56', zIndex: 3 }),
      circle: renderer
        .circle(x + 40, y - 34, 5)
        .attr({ stroke: '#557395', fill: '#0d2b56', zIndex: 4, style: `cursor: pointer` }),
      lines: renderer.path(path).attr({ stroke: '#557395', zIndex: 4 }),
      text: renderer.text('频率:' + indexToPlot(this.point.x), x - 46, y - 30).attr({
        zIndex: 4,
        style: `font-size: 0.6em; fill: #f3f3f3`
      }),
      destroy() {
        this.rect.destroy()
        this.circle.destroy()
        this.lines.destroy()
        this.text.destroy()
        ctx.dialog = null
      },
      hide() {
        this.rect.hide()
        this.circle.hide()
        this.lines.hide()
        this.text.hide()
      },
      show() {
        this.rect.show()
        this.circle.show()
        this.lines.show()
        this.text.show()
      }
    }
    this.dialog.rect.add()
    this.dialog.circle
      .on('click', () => {
        this.dialog.destroy()
      })
      .add()
    this.dialog.lines.add()
    this.dialog.text.add()
  }
  getPoints(item) {
    const { points, data, xData, yData } = item
    if (points.length > 0) {
      return points
    } else if (data.length > 0) {
      return data
    } else {
      return xData.map((x, i) => [x, yData[i]])
    }
  }
  findClosestPoint(item) {
    let minDist = Infinity
    let closestPoint = null
    const points = this.getPoints(item)
    let len = points.length
    this.pLen = len
    for (let i = 0; i < len; i++) {
      const p = points[i]
      const dist = Math.sqrt(this.plotX - p.plotX)
      if (dist < minDist) {
        minDist = dist
        closestPoint = p
      }
    }
    return closestPoint
  }
  update() {
    this.updatePoint()
  }
  updatePoint() {
    const points = this.getPoints(this.chart.series[0])
    const currentPoint = points.find(p => p.x === this.coorX)
    if (currentPoint) {
      this.setPointInfo(currentPoint)
      if (points.length !== this.pLen) {
        this.pLen = points.length
        this.visible && this.drawCustomShape()
      }
    } else {
      this.destroy()
    }
  }
  registeDragEvents() {
    this.text.on('mousedown', event => {
      this.dragEvent(event)
    })
    this.marker.on('mousedown', event => {
      this.dragEvent(event)
    })
  }
  dragEvent(event) {
    this.dragMarker.children[0].children[1].innerHTML = this.index
    this.chart.update({ chart: { zoomType: '' } })
    const left = this.x - 12
    this.dragMarker.style.left = left + 'px'
    this.dragMarker.style.display = 'block'
    const disX = event.clientX - this.dragMarker.offsetLeft
    document.onmousemove = ev => {
      this.isMove = true
      const l = ev.clientX - disX
      this.dragMarker.style.left = l + 'px'
    }
    document.onmouseup = ev => {
      document.onmousemove = null
      document.onmouseup = null
      this.chart.update({ chart: { zoomType: 'xy' } })
      this.dragMarker.style.display = 'none'
      if (!this.isMove) {
        this.clickEvent()
        return
      }
      this.isMove = false
      const l = ev.clientX - disX + 14
      this.plotX = l - this.chart.plotLeft
      this.markerPoint()
    }
  }
  clickEvent() {
    if (this.chart.activeMarker === this) {
      return
    }
    this.chart.activeMarker?.removeActive()
    this.chart.activeMarker = this
    this.chart.activeMarker.addActive()
  }
  removeActive() {
    this.isActive = false
    this.drawCustomShape()
    if (!this.visible) {
      this.hide()
    }
    document.onkeydown = null
  }
  addActive() {
    this.isActive = true
    document.onkeydown = event => {
      const { key } = event
      if (key === 'ArrowRight' || key === 'ArrowLeft') {
        const points = this.getPoints(this.chart.series[0])
        const offset = key === 'ArrowRight' ? 1 : -1
        const index = this.point.x + offset
        if (index > points.length - 1 || index < 0) {
          return
        }
        this.point = points[index]
        this.plotX = this.point.plotX
        this.drawCustomShape()
      }
    }
    this.drawCustomShape()
  }
  hide() {
    this.visible = false
    try {
      this.marker.hide()
      this.text.hide()
      this.dialog?.hide()
    } catch {
      /* empty */
    }
  }
  show() {
    if (this.visible) {
      return
    }
    this.visible = true
    try {
      this.marker.show()
      this.text.show()
      this.dialog?.show()
    } catch {
      /* empty */
    }
  }
  destroy() {
    if (this.marker) {
      this.marker.destroy()
    }
    if (this.text) {
      this.text.destroy()
    }
    if (this.dialog) {
      this.dialog.destroy()
    }
  }
}
